package com.itheima.project.face.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.project.basic.ResponseWrap;
import com.itheima.project.constant.AppletCacheConstant;
import com.itheima.project.enums.DishEnum;
import com.itheima.project.enums.StoreEnum;
import com.itheima.project.exception.ProjectException;
import com.itheima.project.face.DishFace;
import com.itheima.project.feign.FileFeign;
import com.itheima.project.pojo.Dish;
import com.itheima.project.pojo.DishFlavor;
import com.itheima.project.service.IDishFlavorService;
import com.itheima.project.service.IDishService;
import com.itheima.project.utils.BeanConv;
import com.itheima.project.utils.EmptyUtil;
import com.itheima.project.utils.ExceptionsUtil;
import com.itheima.project.vo.DishVo;
import com.itheima.project.vo.file.FileVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName DishFaceImpl.java
 * @Description 菜品接口实现
 */
@Slf4j
@Service
public class DishFaceImpl implements DishFace {

    @Autowired
    IDishService dishService;

    @Autowired
    IDishFlavorService dishFlavorService;

    @Autowired
    FileFeign fileFeign;

    @Autowired
    RedissonClient redissonClient;

    @Override
    public Page<DishVo> findDishVoPage(DishVo dishVo, int pageNum, int pageSize) throws ProjectException {
        try {
            // 1.  调用service根据条件查询
            Page<Dish> dishPage = dishService.findDishVoPage(dishVo, pageNum, pageSize);

            // 2.  结果集转换
            Page<DishVo> dishVoPage = BeanConv.toPage(dishPage, DishVo.class);
            List<DishVo> records = dishVoPage.getRecords();

            if (!EmptyUtil.isNullOrEmpty(records)) {
                records.forEach(n -> {
                    // 3.  查询到的数据处理图片回显
                    ResponseWrap<List<FileVo>> responseWrap = fileFeign.findFileVoByBusinessId(n.getId());
                    List<FileVo> datas = responseWrap.getDatas();
                    n.setFileVo(EmptyUtil.isNullOrEmpty(datas) ? new FileVo() : datas.get(0));

                    // 4.  查询到的数据处理口味回显
                    List<DishFlavor> flavorList = dishFlavorService.findDishFlavorByDishId(n.getId());
                    n.setHasDishFlavor(flavorList.stream().map(DishFlavor::getDataKey).collect(Collectors.toList()));
                });
            }
            return dishVoPage;
        } catch (Exception e) {
            log.error("查询菜品列表异常: {}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(DishEnum.PAGE_FAIL);
        }
    }

    @Override
    @Transactional
    public DishVo createDish(DishVo dishVo) throws ProjectException {
        try {
            // 创建菜品
            DishVo dishVoResult = BeanConv.toBean(dishService.createDish(dishVo), DishVo.class);
            dishVoResult.setHasDishFlavor(dishVo.getHasDishFlavor());

            //绑定附件
            if (!EmptyUtil.isNullOrEmpty(dishVoResult)){
                fileFeign.bindBusinessId(FileVo.builder()
                        .businessId(dishVoResult.getId())
                        .id(dishVo.getFileVo().getId()).build());
                dishVoResult.setFileVo(FileVo.builder()
                        .pathUrl(dishVo.getFileVo().getPathUrl())
                        .businessId(dishVoResult.getId())
                        .id(dishVo.getFileVo().getId()).build());
            }
            //****构建初始化库存****
            String key = AppletCacheConstant.REPERTORY_DISH+dishVoResult.getId();
            RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
            atomicLong.set(dishVoResult.getDishNumber());
            return dishVoResult;
        } catch (ProjectException e) {
            log.error("创建菜品信息异常: {}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(StoreEnum.PAGE_FAIL);
        }
    }

    @Override
    @Transactional
    public Boolean updateDish(DishVo dishVo) throws ProjectException {
        Boolean flag = false;
        //菜品库存锁，前段小程序点餐或后台修改订单项都需要加锁
        String keyLock = AppletCacheConstant.REPERTORY_DISH_LOCK+dishVo.getId();
        RLock lock = redissonClient.getLock(keyLock);
        //添加可重入锁
        try {
            if (lock.tryLock(
                    AppletCacheConstant.REDIS_WAIT_TIME,
                    AppletCacheConstant.REDIS_LEASETIME,
                    TimeUnit.SECONDS)){
                //修改菜品
                flag = dishService.updateDish(dishVo);
                //处理菜品图片
                if (flag){
                    //移除业务原图片，并绑定新的图片到业务上
                    fileFeign.replaceBindBusinessId(
                            FileVo.builder()
                                    .businessId(dishVo.getId())
                                    .id(dishVo.getFileVo().getId())
                                    .build());
                }
                //****构建redis库存*****
                String key = AppletCacheConstant.REPERTORY_DISH+dishVo.getId();
                RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
                atomicLong.set(dishVo.getDishNumber());
                return flag;
            }
        } catch (InterruptedException e) {
            log.warn("修改菜品产生并发dishId:{}",dishVo.getId());
            throw new ProjectException(DishEnum.UPDATE_FAIL);
        }finally {
            lock.unlock();
        }
        return flag;
    }
    @Transactional
    @Override
    public Boolean deleteDish(List<Long> checkedIds) throws ProjectException {
        try {
            Boolean flag = dishService.deleteDish(checkedIds);
            for (Long checkedId : checkedIds) {
                //****删除菜品库存*****
                String key = AppletCacheConstant.REPERTORY_DISH+checkedId;
                RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
                atomicLong.delete();
                //删除图片
                fileFeign.deleteFileVoByBusinessId(FileVo.builder().businessId(checkedId).build());
            }
            return flag;
        } catch (Exception e) {
            log.error("删除菜品异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(DishEnum.DELETE_FAIL);
        }
    }
    @Override
    public DishVo findDishByDishId(Long dishId) throws ProjectException {
        try {
            //按菜品ID查找菜品
            Dish dish = dishService.getById(dishId);
            if (!EmptyUtil.isNullOrEmpty(dish)){
                return BeanConv.toBean(dish,DishVo.class);
            }
            return null;
        } catch (Exception e) {
            log.error("查找菜品所有菜品异常：{}", ExceptionsUtil.getStackTraceAsString(e));
            throw new ProjectException(DishEnum.SELECT_DISH_FAIL);
        }
    }
}
